﻿using BrightIdeasSoftware;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using UIControls;
using BO;
using System.Collections.ObjectModel;
using System.Reflection;

namespace UI.Core
{
    public partial class EditFormBase : FormBase
    {
        protected List<EditRecord> UndoList;
        protected List<EditRecord> RedoList;
        Assembly asm = null;
        public EditFormBase()
        {
            InitializeComponent();
            AddOtherControl();
            if (!Utility.IsDesignMode())
            {
                txtSearch.TextBox.TextChanged += txtSearch_TextChanged;

                cmbProperty.ComboBox.DropDownStyle = ComboBoxStyle.DropDownList;

                UndoList = new List<EditRecord>();
                RedoList = new List<EditRecord>();
                asm = Assembly.Load(GlobalVar.BOAssembly);

            }
            else
            {
                this.Text = "Design";
            }
        }
        protected virtual void AddOtherControl() { }



        public UIControls.Grid.OSGrid MyGrid { get; set; }

        // protected MyDb db;
        private void btnQuery_Click(object sender, EventArgs e)
        {
            var ct = sender as Control;
            ct.Enabled = false;
            Cursor = Cursors.WaitCursor;
            // db = new MyDb();
            UndoList.Clear();
            RedoList.Clear();
            OnQuery();
            ct.Enabled = true;
            Cursor = Cursors.Default;

        }
        private void txtSearch_TextChanged(object sender, EventArgs e)
        {

            Cursor = Cursors.WaitCursor;
            OnSearch();
            Cursor = Cursors.Default;
        }
        protected void FildChanged(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            RedoList.Clear();
            UndoList.Clear();
            OnFiledChanged();
            txtSearch.Focus();
            Cursor = Cursors.Default;
        }

        protected void OnFiledChanged()
        {
            FetchData();
            DataBind();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            var ct = sender as Control;
            ct.Enabled = false;
            Cursor = Cursors.WaitCursor;
            var obj = OnAdd();

            object[] a = new object[] { obj };
            MyGrid.InsertObjects(0, a);
            MyGrid.RefreshObject(obj);

            var record = new EditRecord(OpreateType.Add, obj, null, null);
            UndoList.Add(record);


            ct.Enabled = true;
            Cursor = Cursors.Default;
            MyGrid.SelectedIndex = 0;
            MyGrid.Focus();
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            var idx = MyGrid.SelectedIndex;
            var ct = sender as Control;
            ct.Enabled = false;
            Cursor = Cursors.WaitCursor;
            OnRemove();
            ct.Enabled = true;
            Cursor = Cursors.Default;
            if (MyGrid.Items.Count > idx)
            {
                MyGrid.SelectedIndex = idx;
                MyGrid.Focus();
            }
            else
            {
                MyGrid.SelectedIndex = 0;
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            var ct = sender as Control;
            ct.Enabled = false;
            Cursor = Cursors.WaitCursor;
            try
            {
                OnSave();
            }
            finally
            {
                UndoList.Clear();
                RedoList.Clear();
                ct.Enabled = true;
                Cursor = Cursors.Default;
            }
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            var ct = sender as Control;
            ct.Enabled = false;
            OnExport();
            ct.Enabled = true;
            Cursor = Cursors.Default;
        }
        virtual protected void OnSave()
        {

        }
        virtual protected void OnQuery()
        {
            if (IsSecurityMode)
                return;
            FetchData();
            DataBind();
        }

        virtual protected void FetchData()
        {


        }

        virtual protected object OnAdd()
        {
            return null;
        }

        private void OnRemove()
        {
            var removedList = MyGrid.SelectedObjects;

            foreach (var item in removedList)
            {
                RemovedList.Add(item);
            }
            MyGrid.RemoveObjects(MyGrid.SelectedObjects);

            var record = new EditRecord(OpreateType.Remove, removedList, null, null);
            UndoList.Add(record);
        }
        protected List<object> RemovedList = new List<object>();
        virtual protected void OnExport()
        {
            var dt = MyGrid.GenerateDataTable();
            var excel = new ExcelAdapter();
            excel.SaveExcel(dt, "", this.Text, this.Text);
        }
        virtual protected void OnSearch()
        {
            TimedFilter(MyGrid, SearchText);
        }
        virtual protected void OnGridFilterd(UIControls.Grid.OSGrid.FilterdEventArgs e)
        {

        }
        protected string SearchText { get { return txtSearch.TextBox.Text; } }

        virtual protected void TimedFilter(ObjectListView olv, string txt)
        {
            if (olv.Objects == null)
                return;
            this.TimedFilter(olv, txt, 0);
        }

        virtual protected void TimedFilter(ObjectListView olv, string txt, int matchKind)
        {
            if (olv.Objects == null)
                return;
            TextMatchFilter filter = null;
            if (!String.IsNullOrEmpty(txt))
            {
                switch (matchKind)
                {
                    case 0:
                    default:
                        filter = TextMatchFilter.Contains(olv, txt);
                        break;
                    case 1:
                        filter = TextMatchFilter.Prefix(olv, txt);
                        break;
                    case 2:
                        filter = TextMatchFilter.Regex(olv, txt);
                        break;
                }
            }
            // Setup a default renderer to draw the filter matches
            if (filter == null)
                olv.DefaultRenderer = null;
            else
            {
                olv.DefaultRenderer = new HighlightTextRenderer(filter);

                // Uncomment this line to see how the GDI+ rendering looks
                olv.DefaultRenderer = new HighlightTextRenderer { Filter = filter, UseGdiTextRendering = false };
            }

            // Some lists have renderers already installed
            HighlightTextRenderer highlightingRenderer = olv.GetColumn(0).Renderer as HighlightTextRenderer;
            if (highlightingRenderer != null)
                highlightingRenderer.Filter = filter;

            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            olv.ModelFilter = filter;
            stopWatch.Stop();

            IList objects = olv.Objects as IList;

        }

        protected void InitGrid()
        {

            this.MyGrid.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.DoubleClick;
            this.MyGrid.GridLines = true;
            //MyGrid.LabelEdit = true;
            MyGrid.UseFiltering = true;
            MyGrid.FullRowSelect = true;
            MyGrid.AllowColumnReorder = true;

            MyGrid.HeaderWordWrap = true;
            // MyGrid.RowHeight = 25;
            MyGrid.CellEditKeyEngine.SetKeyBehaviour(Keys.Enter, CellEditCharacterBehaviour.ChangeRowDown, CellEditAtEdgeBehaviour.ChangeColumn);
            // this.MyGrid.AddDecoration(new EditingCellBorderDecoration(true));

            MyGrid.Filterd += grid_Filterd;


            MyGrid.CellEditStarting += grid_CellEditStarting;
            MyGrid.CellEditFinishing += grid_CellEditFinishing;
            MyGrid.CellEditValidating += grid_CellEditValidating;

        }
        void grid_Filterd(object sender, UIControls.Grid.OSGrid.FilterdEventArgs e)
        {
            OnGridFilterd(e);
        }

        protected IEnumerable GridDataSource { get; set; }
        Dictionary<string, string> dit = new Dictionary<string, string>();
        protected virtual void DataBind()
        {

            MyGrid.SetObjects(GridDataSource);

            cmbProperty.ComboBox.DataSource = null;
            dit.Clear();
            foreach (OLVColumn col in MyGrid.Columns)
            {
                if (col.IsEditable && col.IsVisible)
                {
                    dit.Add(col.AspectName, col.Text);
                }
            }
            if (dit.Count > 0)
            {
                cmbProperty.ComboBox.DataSource = dit.ToArray();
                cmbProperty.ComboBox.DisplayMember = "Value";
                cmbProperty.ComboBox.ValueMember = "Key";
            }
        }
        private double _TotalAmt;
        protected double TotalAmt
        {
            get { return _TotalAmt; }
            set
            {
                _TotalAmt = value;
                this.stTotalAmt.Text = string.Format(" 合计 : {0} ", value);
            }
        }
        private long _RowCount;
        protected long RowCount
        {
            get { return _RowCount; }
            set
            {
                _RowCount = value;
                stRowCount.Text = string.Format(" 记数 : {0} ", value);
            }
        }



        #region Cell editing example

        private void grid_CellEditStarting(object sender, CellEditEventArgs e)
        {
            OnCellEditStarting(e);
        }
        virtual protected void OnCellEditStarting(CellEditEventArgs e)
        {

        }
        private void grid_CellEditValidating(object sender, CellEditEventArgs e)
        {

            OnCellEditValidating(e);
        }
        virtual protected void OnCellEditValidating(CellEditEventArgs e)
        {

        }

        private void grid_CellEditFinishing(object sender, CellEditEventArgs e)
        {

            OnGridFilterd(new UIControls.Grid.OSGrid.FilterdEventArgs(MyGrid.FilteredObjects));
            OnCellEditFinishing(e);

            if (!object.Equals(e.Value, e.NewValue))
            {

                var record = new EditRecord(OpreateType.Edit, e.RowObject, e.Column.AspectName, e.Value);
                UndoList.Add(record);
            }
        }



        #endregion
        virtual protected void OnCellEditFinishing(CellEditEventArgs e)
        {

        }

        private void btnUnDo_Click(object sender, EventArgs e)
        {
            if (UndoList.Count == 0)
                return;
            var r = UndoList.Last();

            switch (r.Opreate)
            {
                case OpreateType.Edit:
                    EditObject(r);
                    break;
                case OpreateType.Remove:
                    AddObject(r);
                    break;
                case OpreateType.Add:
                    RemoveObjcet(r);
                    break;
            }

            UndoList.Remove(r);
            RedoList.Add(r);
        }

        private void btnReDo_Click(object sender, EventArgs e)
        {
            if (RedoList.Count == 0)
                return;
            var r = RedoList.Last();

            switch (r.Opreate)
            {
                case OpreateType.Edit:
                    EditObject(r);
                    break;
                case OpreateType.Add:
                    AddObject(r);
                    break;
                case OpreateType.Remove:
                    RemoveObjcet(r);
                    break;
            }

            RedoList.Remove(r);
            this.UndoList.Add(r);
        }
        void AddObject(EditRecord r)
        {

            if (r.EditObject is ICollection)
            {
                MyGrid.InsertObjects(0, r.EditObject as ICollection);
            }
            else
            {
                object[] a = new object[] { r.EditObject };
                MyGrid.InsertObjects(0, a);
            }

        }

        void RemoveObjcet(EditRecord r)
        {

            if (r.EditObject is ICollection)
            {
                MyGrid.RemoveObjects(r.EditObject as ICollection);
            }
            else
            {
                MyGrid.RemoveObject(r.EditObject);
            }


        }
        void EditObject(EditRecord r)
        {
            var ot = r.EditObject.GetType();
            var p = ot.GetProperty(r.PropertyName);
            var preChangedValue = p.GetValue(r.EditObject, null);
            p.SetValue(r.EditObject, r.OldValue, null);
            MyGrid.RefreshObject(r.EditObject);
            MyGrid.SelectObject(r.EditObject);
            r.OldValue = preChangedValue;
        }
        protected virtual void NotifyForChange()
        {
            if (btnSave.Enabled && btnSave.Visible)
            {
                if (this.UndoList.Count != 0)
                {
                    var r = MessageBox.Show("是否保存所做的修改", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                    if (r == System.Windows.Forms.DialogResult.Yes)
                    {
                        btnSave_Click(this, null);
                    }
                }
            }
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            NotifyForChange();

        }

        private void btnImport_Click(object sender, EventArgs e)
        {
            ExcelAdapter excel;
            var openFileDlg = new OpenFileDialog();
            if (openFileDlg.ShowDialog(this) != DialogResult.OK)
                return;
            excel = new ExcelAdapter(openFileDlg.FileName);

            excel.openConnection();
            var dt = excel.readEntireSheet();
            excel.closeConnection();
            MyGrid.AddRowsFromDataTable(dt);
        }

        private void btnReVal_Click(object sender, EventArgs e)
        {
            try
            {
                if (cmbProperty.ComboBox.SelectedValue == null)
                    return;
                var list = MyGrid.FilteredObjects.OfType<BusinessBaseEx>().ToArray();
                if (list == null)
                    return;
                if (list.Count() == 0)
                    return;

                var pstr = cmbProperty.ComboBox.SelectedValue.ToString();
                var p = list[0].GetType().GetProperty(pstr);
                if (p == null)
                    return;
                object val = txtPropertyValue.Text;
                if (MessageBox.Show(this, string.Format("是否将【{0}】设置为【{1}】?", cmbProperty.ComboBox.Text, val), "提示", MessageBoxButtons.YesNo) != System.Windows.Forms.DialogResult.Yes)
                    return;
                if (p.PropertyType == typeof(bool))
                {
                    if (val.Equals("是"))
                        val = true;
                    else if (val.Equals("否"))
                        val = false;
                }
                BatchSetProperty(list, p, val);
                MyGrid.RefreshObjects(list);
            }
            catch (ExceptionEx exp)
            {
                new ExceptionExShowForm(new ExceptionEx("设置失败,请检查数据")).ShowDialog(this);
            }

        }
        protected virtual void BatchSetProperty(BusinessBaseEx[] list, PropertyInfo p, object val)
        {
            foreach (var item in list)
            {
                p.SetValue(item, Convert.ChangeType(val, p.PropertyType), null);
            }
        }
        private void EditFormBase_Load(object sender, EventArgs e)
        {

        }


    }
}
